﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace Dycox.Linq
{
    public class ListItemConverter : TypeConverter
    {

        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            bool can = false;
            if (destinationType.IsArray)
            {
                can = this.CanConvertTo(context, destinationType.GetElementType());
            }
            return can || base.CanConvertTo(context, destinationType);
        }

        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
        {
            if (value != null)
            {
                if (value is Array)
                {
                    Type type;
                    if (destinationType.IsArray)
                        type = destinationType.GetElementType();
                    else
                        type = typeof(string);
                    Array arsrc = value as Array, ardest;
                    if (arsrc == null)
                    {
                        arsrc = Array.CreateInstance(type, 1);
                        arsrc.SetValue(value, 0);
                    }
                    ardest = Array.CreateInstance(type, arsrc.Length);

                    for (int i = 0; i < arsrc.Length; i++)
                    {
                        object v = this.ConvertTo(context, culture, arsrc.GetValue(i), type);
                        ardest.SetValue(v, i);
                    }

                    if (destinationType == typeof(string))
                        return string.Join(culture.TextInfo.ListSeparator, (string[])ardest);
                    else
                        return ardest;
                }

                IListItem item = value as IListItem;
                if (destinationType == typeof(string) && item != null)
                    return item.Text;
            }

            return base.ConvertTo(context, culture, value, destinationType);
        }

        public virtual IListItem[] GetStandardItems(ITypeDescriptorContext context)
        {
            if (context != null)
            {
                QueryArgs args;
                QueryArgsSurrogate surrogate;

                surrogate = context.Instance as QueryArgsSurrogate;
                if (surrogate != null) args = surrogate.QueryArgs;
                else args = context.Instance as QueryArgs;

                QueryProperty qp = context.PropertyDescriptor as QueryProperty;
                if (args != null && qp != null)
                    return args.GetStandardItems(qp);
            }

            return null;
        }

        public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
        {
            IListItem[] array;

            if (context != null)
            {
                array = GetStandardItems(context);
            }
            else
                array = null;

            if (array == null)
            {
                var coll = base.GetStandardValues(context);
                List<IListItem> list = new List<IListItem>(coll.Count);
                foreach (object value in coll)
                {
                    if (value is IListItem) list.Add((IListItem)value);
                    else list.Add(new GeneralListItem(value));
                }
            }

            return new StandardValuesCollection(array);
            
        }

        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
        {
            if (context != null)
            {
                QueryProperty qp = context.PropertyDescriptor as QueryProperty;
                if (qp != null) return qp.StandardItemsSupport != StandardItemsSupport.None;
            }

            return false;
        }

        public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
        {
            //return base.GetStandardValuesExclusive(context);
            return true;
        }

        class GeneralListItem : IListItem
        {
            public GeneralListItem(object value)
            {
                _value = value;
                if (value != null)
                    _text = value.ToString();
            }

            private string _text;
            public string Text
            {
                get { return _text; }
            }

            private object _value;
            public object Value
            {
                get { return _value; }
            }
        }

    }

    //public class ListItemValueConverter : TypeConverter
    //{
    //    public ListItemValueConverter()
    //    {
    //    }

    //    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    //    {
    //        return destinationType.IsAssignableFrom(destinationType) || base.CanConvertTo(context, destinationType);
    //    }

    //    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
    //    {
    //        if (value == null) return null;

    //        IListItem item = value as IListItem;
    //        if (item != null)
    //        {
    //            object v = item.Value;

    //            if (destinationType == typeof(string))
    //                return v == null ? string.Empty : v.ToString();

    //            if (v == null || destinationType.IsAssignableFrom(v.GetType()))
    //                return v;
    //        }

    //        return base.ConvertTo(context, culture, value, destinationType);
    //    }
    //}
}
